﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Runtime.Serialization.Json;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Net;
using System.Text;
using System.IO;
using System.Threading;
using System.IO.Compression;

namespace Parking
{
    /// <summary>
    /// Логика взаимодействия для MainWindow.xaml
    /// </summary>
    public partial class MainWindow
    {

        public const int _sentRowNumber = 8;
        private static Mutex MutexSendThreadFlag;
        private settings SettingsWindow = new settings();
        public static MySettings MySettingsObject = new MySettings();
        private DBBase _db;

        public MainWindow()
        {
            try
            {
                InitializeComponent();
            }
            catch (Exception e)
            {
                MessageBox.Show("форма"+e.Message);
            }
            try
            {
                _db = new DBBase();
            }
            catch (Exception e)
            {
                MessageBox.Show("1\n" + e.Message);
                Application.Current.Shutdown();
            }

            
            try
            {
                
                Upd();
            }
            catch (Exception e)
            {
                MessageBox.Show("2\n" + e.Message);
                Console.WriteLine(e.Message);
                Application.Current.Shutdown();
            }
              
            try
            {

                dataGrid1.SelectionMode = DataGridSelectionMode.Single;
            }
            catch (Exception e)
            {
                MessageBox.Show("3\n"+e.Message);
                Application.Current.Shutdown();
            }

            if (MySettingsObject.login == "")
            {
                SettingsWindow.label3.Content = "Укажите ваш логин и пароль";
                SettingsWindow.ShowDialog();
                SettingsWindow.label3.Content = "";
            }

            try{
            StatusBarItem1.Content = MySettingsObject.login;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }

        /// <summary>
        /// Обновить данные в главной таблице машин
        /// </summary>
        public void Upd()
        {
            //string[] ColumnNames = {"№","Въезд","Водитель","Машина","Номер","Регион","Примечание","","","","","","" };
            var myTable = LoadData();
            
            if (myTable == null)
            {
                return;
            }


            try
            {
                dataGrid1.Columns.Clear();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                MessageBox.Show("2.1\n" + ex.Message);
            }
            
            
            foreach (DataColumn col in myTable.Columns)
            {
                dataGrid1.Columns.Add(
                    new DataGridTextColumn
                    {
                        Header = col.ColumnName,
                        Binding = new Binding(String.Format("[{0}]", col.ColumnName))
                    });
            }
             
            dataGrid1.DataContext = myTable;
            dataGrid1.ItemsSource = myTable.Rows;
        }

        private DataTable LoadData()
        {
            try
            {
                var myTable = _db.LoadData();
                return myTable;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                MessageBox.Show("2.0\n" + ex.Message);
            }

            
            return null;
        }

        private void Button1Click(object sender, RoutedEventArgs e)
        {
            Who whoWindow;

            try
            {
                whoWindow = new Who(_db, this);
            }
            catch (Exception err)
            {
                MessageBox.Show("new " + err.Message + "\n" + err.Source + "\n" + err.Data);
                return;
            }
            
            
            try
            {
                whoWindow.ShowDialog();
            }
            catch (Exception err)
            {
                MessageBox.Show("Show " + err.Message + "\n" + err.Source + "\n" + err.Data);
                return;
            }

            Upd();

            //впустили машину, стучим на сервер
            StartSendThread();
        }
        /*
        private void Button2Click(object sender, RoutedEventArgs e)
        {
            var whoWindow = new Who(_db,this,false);
            whoWindow.Show();
        }
        */
        private void dataGrid1_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var row = (dataGrid1.SelectedItem as DataRow);


            //MessageBox.Show(dataGrid1.ColumnFromDisplayIndex(0).GetType().ToString());
            //row.Table.AcceptChanges();
            if (row == null) return;
            
            string s = row.Field<string>(3) + " " + row.Field<string>(4) + " " + row.Field<string>(5);
            if (MessageBox.Show("Выезжает " + s, "Выезд машины", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.No)
            {
                dataGrid1.SelectedIndex = -1;
                return;

            }

            long zz=row.Field<long>(0);
            var z = zz.ToString();
            _db.SetDeparture(z, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            Upd();
            
            //выпустили машину. стучим на сервер.
            StartSendThread();
        }

        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
            Application.Current.Shutdown();
        }

        private void MenuItem_Click_1(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Process.Start("help.htm");
        }

        private void button2_Click(object sender, RoutedEventArgs e)
        {
            StartSendThread();
        }

        private void StartSendThread()
        {
            (new Thread(delegate()
            {
                bool CreatedNew;
                MutexSendThreadFlag = new Mutex(true, "SendThreadFlag", out CreatedNew);
                // Проверяем не создавался ли он раньше
                if (CreatedNew == true)
                {
                    //если мютекс создался новый, то отсылаем данные
                    send();

                    //и отпускаем мьютекс
                    MutexSendThreadFlag.ReleaseMutex();
                    MutexSendThreadFlag.Dispose();
                }
            })).Start();
        }

        /// <summary>
        /// внутренняя структура
        /// </summary>
        [Serializable]
        private class Car
        {
            // если изменить назввания, то они и покажутся в сериализованной строке
            public string ID;
            public string TimeIn;
            public string TimeOut;
            public string Driver;
            public string CarModel;
            public string NumberCar;
            public string Region;
            public string Note;

            public Car(DataRow row)
            {
                ID = row[0].ToString();
                TimeIn = row[1].ToString();
                Driver = row[2].ToString();
                CarModel = row[3].ToString();
                NumberCar = row[4].ToString();
                Region = row[5].ToString();
                Note = row[6].ToString();
                TimeOut = row[7].ToString();
            }
        }
        /// <summary>
        /// Получить записи из таблицы, в виде подходящем для сериализации
        /// </summary>
        /// <returns></returns>
        private IEnumerable<Car> AllRecords()
        {
            var source = _db.LoadAllData();
            // row[0].ToString() != "" заменить на нужное условие тут, либо в запросе
            List<Car> cars = (from DataRow row in source.Rows where (row[_sentRowNumber].ToString() == "") select new Car(row)).ToList();
            return cars;
        }
        /// <summary>
        /// Сериализация в строку
        /// </summary>
        /// <param name="cars"></param>
        /// <returns></returns>
        private string JSONSerialize(IEnumerable<Car> cars)
        {
            var stream = new MemoryStream();
            var jsonSer = new DataContractJsonSerializer(typeof(Car));

            stream.WriteByte(91);
            int countCars = 0;
            foreach (var car in cars)
            {
                jsonSer.WriteObject(stream, car);
                countCars++;
                if (countCars < cars.Count()) stream.WriteByte(44);
            }
            stream.WriteByte(93);

            stream.Position = 0;
            var sr = new StreamReader(stream);
            return sr.ReadToEnd();
        }

        private void send()
        {
            string url = "http://park-on.ru/get.php";

            // получили
            var cars = AllRecords();
            // количество
            var count = cars.Count();
            // сериализовали
            var json = JSONSerialize(cars);

            var encoding = new UTF8Encoding();
            var postData = "login=" + MySettingsObject.login;
            postData += "&pwd=" + MySettingsObject.password;
            postData += "&parking=" + MySettingsObject.parking;
            
            // если количество записей больше нуля, тогда добавляем строку 
            if(count>0) postData += "&result=" + json;
            // и выводим количество
            postData += "&count=" + count;

            var data = encoding.GetBytes(postData);

            var httpWReq = (HttpWebRequest)WebRequest.Create(url);

            httpWReq.Method = "POST";
            httpWReq.ContentType = "application/x-www-form-urlencoded";
            httpWReq.ContentLength = data.Length;

            using (var stream = httpWReq.GetRequestStream())
            {
                stream.Write(data,0,data.Length);
            }
            try
            {
                var response = (HttpWebResponse)httpWReq.GetResponse();
                //for (int i = 0; i < response.Headers.Count; ++i)
                //    Console.WriteLine("\nHeader Name:{0}, Value :{1}", response.Headers.Keys[i], response.Headers[i]); 

                string responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
                Console.WriteLine("response.StatusCode = " + response.StatusCode);
                Console.WriteLine("responseString=" + responseString);
                if (responseString=="ok")
                {
                    foreach (var car in cars)
                    {
                        _db.SetSent(car.ID, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                    }                    
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }
        }

        private void MenuItem_Click_2(object sender, RoutedEventArgs e)
        {
            SettingsWindow.ShowDialog();
        }

        private void MenuItem_Click_3(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Process.Start("http://www.park-on.ru/index.php?login="+MySettingsObject.login+"&passw="+MySettingsObject.password);
        }

        private void MenuItem_Click_4(object sender, RoutedEventArgs e)
        {
            Window1 win = new Window1();
            win.ShowDialog();
        }


    }

    /// <summary>
    /// Настройки
    /// </summary>
    public class MySettings
    {
        /// <summary>
        /// Логин
        /// </summary>
        public string login;

        /// <summary>
        /// Пароль
        /// </summary>
        public string password;

        /// <summary>
        /// Парковка
        /// </summary>
        public string parking;

        public MySettings()
        {
            try
            {
                string rawLogin = Properties.Settings.Default.login;
                string rawPassword = Properties.Settings.Default.password;
                string rawParking = Properties.Settings.Default.parking;
                string login;       //логин после расшифровки
                string password;    //пароль после расшифровки
                string parking;    //код данной парковки после расшифровки

                if (rawLogin != "") login = Crypto.Decrypt(rawLogin);
                else login = "";

                if (rawPassword != "") password = Crypto.Decrypt(rawPassword);
                else password = "";

                if (rawParking != "") parking = Crypto.Decrypt(rawParking);
                else parking = "";

                this.login = login;
                this.password = password;
                this.parking = parking;
            }
            catch(Exception e)
            {
                MessageBox.Show(e.Message.ToString());
            }
        }
    }
}
